package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xuecheng.base.exception.XueChengPlusException;
import com.xuecheng.content.mapper.TeachplanMapper;
import com.xuecheng.content.mapper.TeachplanMediaMapper;
import com.xuecheng.content.model.dto.BindTeachplanMediaDto;
import com.xuecheng.content.model.dto.SaveTeachplanDto;
import com.xuecheng.content.model.po.Teachplan;
import com.xuecheng.content.model.po.TeachplanMedia;
import com.xuecheng.content.model.vo.TeachplanVo;
import com.xuecheng.content.service.TeachplanService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class TeachplanServiceImpl implements TeachplanService {

    private static final String MOVE_TYPE_UP = "moveup";
    private static final String MOVE_TYPE_DOWN = "movedown";

    @Autowired
    private TeachplanMapper teachplanMapper;

    @Autowired
    private TeachplanMediaMapper teachplanMediaMapper;

    /**
     * 根据课程id查询课程计划
     * @param courseId 课程id
     * @return
     */
    @Override
    public List<TeachplanVo> findTeachplanTree(Long courseId) {
        List<TeachplanVo> teachplanVos = teachplanMapper.selectTreeNodes(courseId);
        return teachplanVos;
    }

    /**
     * 新增/修改/保存课程计划
     * @param saveTeachplanDto
     */
    @Override
    public void saveTeachplan(SaveTeachplanDto saveTeachplanDto) {

        // 通过课程计划id判断是新增还是修改
        Long teachplanId = saveTeachplanDto.getId();
        if(teachplanId == null) {
            // 新增
            Teachplan teachplan = new Teachplan();
            BeanUtils.copyProperties(saveTeachplanDto, teachplan);

            // 确定排序字段，找到它的同级节点个数，排序字段就是个数加1
            Long courseId = saveTeachplanDto.getCourseId();
            Long parentid = saveTeachplanDto.getParentid();
            int teachplanCount = getTeachplanCount(courseId, parentid);
            teachplan.setOrderby(teachplanCount);

            teachplanMapper.insert(teachplan);
        } else {
            // 修改
            Teachplan teachplan = teachplanMapper.selectById(teachplanId);
            // 将参数复制到teachplan
            BeanUtils.copyProperties(saveTeachplanDto, teachplan);
            teachplanMapper.updateById(teachplan);
        }
    }

    /**
     * 删除课程计划
     * @param id
     */
    @Override
    @Transactional
    public void deleteTeachplan(Long id) {
        // 根据id查询树节点
        Teachplan teachplan = teachplanMapper.selectById(id);

        // 验证是否第一级别的章
        if(teachplan.getGrade() == 1 && teachplan.getParentid() == 0) {
            // 查看是否有小节
            Integer count = teachplanMapper.secondCountById(id);
            if(count > 0) {
                // 是，抛异常提示
                XueChengPlusException.cast("课程计划信息还有子级信息，无法操作");
            }
            // 删除树节点
            teachplanMapper.deleteById(id);
            return;
        }
        // 删除树节点
        teachplanMapper.deleteById(id);
        // 第二级别的小节，查看是否关联的视频信息
        TeachplanMedia teachplanMedia = teachplanMediaMapper.selectOne(
                new LambdaQueryWrapper<TeachplanMedia>()
                        .eq(TeachplanMedia::getTeachplanId, id)
        );
        if(teachplanMedia != null) {
            teachplanMediaMapper.deleteById(teachplanMedia.getId());
        }
    }

    /**
     * 移动课程计划排序
     * @param moveType
     * @param id
     */
    @Override
    @Transactional
    public void moveTeachplan(String moveType, Long id) {
        // 数据的合法性校验
        if (StringUtils.isBlank(moveType) || id == null) {
            XueChengPlusException.cast("移动类型为空或课程计划id为空");
        }
        if (!MOVE_TYPE_UP.equals(moveType) && !MOVE_TYPE_DOWN.equals(moveType)) {
            XueChengPlusException.cast("移动类型不合法");
        }
        // 获取同类型的章节list
        Teachplan teachplan = teachplanMapper.selectById(id);
        Integer grade = teachplan.getGrade();
        if (grade == 1) {
            // 大章节
            LambdaQueryWrapper<Teachplan> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Teachplan::getCourseId, teachplan.getCourseId()).eq(Teachplan::getParentid, 0L).orderByAsc(Teachplan::getOrderby);
            List<Teachplan> teachplans = teachplanMapper.selectList(wrapper);
            // 移动
            move(teachplans, teachplan, moveType);
        } else {
            // 小章节
            LambdaQueryWrapper<Teachplan> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Teachplan::getCourseId, teachplan.getCourseId()).eq(Teachplan::getParentid, teachplan.getParentid()).orderByAsc(Teachplan::getOrderby);
            List<Teachplan> teachplans = teachplanMapper.selectList(wrapper);
            // 移动
            move(teachplans, teachplan, moveType);
        }
    }

    /**
     * 教学计划绑定媒资
     * @param bindTeachplanMediaDto
     */
    @Override
    @Transactional
    public void associationMedia(BindTeachplanMediaDto bindTeachplanMediaDto) {

        // 课程计划id
        Long teachplanId = bindTeachplanMediaDto.getTeachplanId();
        Teachplan teachplan = teachplanMapper.selectById(teachplanId);
        if(teachplan == null) {
            XueChengPlusException.cast("课程计划不存在");
        }

        // 先删除原有记录，根据课程计划id删除它所绑定的媒资
        teachplanMediaMapper.delete(new LambdaQueryWrapper<TeachplanMedia>().eq(TeachplanMedia::getTeachplanId, bindTeachplanMediaDto.getTeachplanId()));

        // 再添加记录
        TeachplanMedia teachplanMedia = new TeachplanMedia();
        BeanUtils.copyProperties(bindTeachplanMediaDto, teachplanMedia);
        teachplanMedia.setCourseId(teachplan.getCourseId());
        teachplanMedia.setMediaFilename(bindTeachplanMediaDto.getFileName());
        teachplanMediaMapper.insert(teachplanMedia);
    }

    /**
     * 课程计划和媒资信息解除绑定
     * @param teachplanId
     * @param mediaId
     */
    @Override
    public void unboundMedia(String teachplanId, String mediaId) {

        // 数据合法效验
        if(StringUtils.isBlank(mediaId) || StringUtils.isBlank(teachplanId)) {
            XueChengPlusException.cast("参数异常");
        }

        // 删除媒资绑定表的数据
        teachplanMediaMapper.delete(new LambdaQueryWrapper<TeachplanMedia>()
                .eq(TeachplanMedia::getMediaId, mediaId)
                .eq(TeachplanMedia::getTeachplanId, teachplanId)); // 前端有bug
    }

    private int getTeachplanCount(Long courseId, long parentId) {
        LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper = queryWrapper.eq(Teachplan::getCourseId, courseId)
                .eq(Teachplan::getParentid, parentId);
        Integer count = teachplanMapper.selectCount(queryWrapper);
        return count + 1;
    }

    private void move(List<Teachplan> teachplans,Teachplan teachplan, String moveType){
        // 获取当前课程计划的索引
        int index = teachplans.indexOf(teachplan);
        // 获取当前课程计划的排序值
        Integer orderby = teachplan.getOrderby();
        // 判断移动类型
        if (MOVE_TYPE_UP.equals(moveType)) {
            // 上移
            if (index == 0) {
                XueChengPlusException.cast("已经处在最上的位置,无法继续上移");
            }
            // 交换课程计划的排序值
            Teachplan lastTeachplan = teachplans.get(index - 1);
            Integer lastOrderby = lastTeachplan.getOrderby();
            teachplan.setOrderby(lastOrderby);
            lastTeachplan.setOrderby(orderby);
            // 更新
            teachplanMapper.updateById(teachplan);
            teachplanMapper.updateById(lastTeachplan);
        } else {
            // 下移
            int max = teachplans.size() - 1;
            if (index == max) {
                XueChengPlusException.cast("已经处在最下的位置,无法继续下移");
            }
            // 交换课程计划的排序值
            Teachplan nextTeachplan = teachplans.get(index + 1);
            Integer nextOrderby = nextTeachplan.getOrderby();
            teachplan.setOrderby(nextOrderby);
            nextTeachplan.setOrderby(orderby);
            // 更新
            teachplanMapper.updateById(teachplan);
            teachplanMapper.updateById(nextTeachplan);
        }
    }
}
